﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace TratamentoRIWikipedia.Indexacao
{
    class Valor
    {
        public Valor()
        {
            documento = 0;
            posicao = new ArrayList(); ;
        }
        private int documento;
        public int Documento
        {
            get { return documento; }
            set { documento = value; }
        }
        private ArrayList posicao;
        public ArrayList Posicao
        {
            get { return posicao; }
            set { posicao = value; }
        }
    }

    class Indice
    {
        public static void GeraIndice()
        {
            StreamReader arquivo = new StreamReader("WikiDocSemStopWord.txt");

            Dictionary<string, ArrayList> Indexacao = new Dictionary<string, ArrayList>(); //array list de objetos Valor com informações dessa palavra
            Valor dadosValor = new Valor();
            ArrayList listValor = new ArrayList();
            string linhaArquivo;
            string[] elementoDoc;
            string[] termos;
            int termosCount, posicao = 0;

            //Leu a linha do arquivo - ou seja 1 documento
            while ((linhaArquivo = arquivo.ReadLine()) != null)
            {
                string[] separador = new string[] { "<#id#>", "<#title#>", "<#text#>" };
                elementoDoc = linhaArquivo.Split(separador, StringSplitOptions.RemoveEmptyEntries);
               

                //if para ignorar doucmentos sem texto
                if (elementoDoc.Length > 2)
                {
                    termos = elementoDoc[0].ToString().Split(' '); // pega o titulo
                    termos = termos.Concat(elementoDoc[2].ToString().Split(' ')).ToArray(); // pega o texto e concatena
                    //pega a quantidade de palavras no documento
                    int tamanho = termos.Count();

                    posicao = 0; //zera contagem do cursor no documento

                    //para cada palavra do documento faça
                    for (int i = 0; i < tamanho; i++)
                    {
                        listValor = new ArrayList(); //zera a lista de valor quando mudar de palavra ou posição

                        string documento = elementoDoc[1]; //Pega id do documento
                        termosCount = termos[i].Count(); //Pega o tamanho da palavra atual

                        //Se o hash não tem a palavra adiciona uma nova entrada
                        if (!Indexacao.ContainsKey(termos[i]))
                        {
                            dadosValor.Documento = int.Parse(elementoDoc[1]);
                            dadosValor.Posicao.Add(posicao);
                            posicao += termosCount + 1;
                            listValor.Add(dadosValor);

                            Indexacao.Add(termos[i], listValor);//adiciona no hash 
                            dadosValor = new Valor(); //cria um novo objeto com dados da palavra
                        }
                        else
                        {
                            string chaveIndice = termos[i];   //Pega a palavra que é chave
                            ArrayList listAux = new ArrayList();  // obj auxiliar para recuperar a informações da chave
                            Indexacao.TryGetValue(chaveIndice, out listAux);  //Recupera a Lista de objeto Valor a partir da chave
                            bool novoDoc = true;
                            Valor objValoraux = null;
                            //A listAux possui algum objeto Valor que o Id do documento é igual ao Atual ?
                            foreach (Valor item in listAux)
                            {
                                if (item.Documento == int.Parse(elementoDoc[1]))
                                {
                                    novoDoc = false;
                                    objValoraux = item; //Recebe o objeto Valor na posição que é igual o ID do documento
                                    break;
                                }
                            }

                            //A palavra existe em um novo documento ainda não adicionado no ArrayList? 
                            //Adiciona um novo objeto Valor no ArrayList de Valor 
                            if (novoDoc)
                            {
                                dadosValor.Documento = int.Parse(elementoDoc[1]);
                                dadosValor.Posicao.Add(posicao);
                                listAux.Add(dadosValor); //adiciona o novo objeto no array list do id documento
                            }
                            else
                            {
                                //Existe a palavra no documento atual ? 
                                // Na lista de valor ir no objeto do documento atual 
                                // Adiciona na lista de posição mais uma posição 
                                objValoraux.Posicao.Add(posicao);
                            }

                            dadosValor = new Valor();
                            posicao += termosCount + 1;


                        }

                    }

                }

            }

            arquivo.Close();

            gravaArquivoIndice(Indexacao);

        }

        public static void gravaArquivoIndice(Dictionary<string, ArrayList> Indice)
        {
            StreamWriter arquivoIndice = new StreamWriter("Indice.txt");
            foreach (KeyValuePair<string, ArrayList> item in Indice)
            {


                //Valor objetoValor = (valor)item.Value[;

                arquivoIndice.Write(item.Key);
                arquivoIndice.Write('|');
                foreach (Valor objetoValor in item.Value)
                {
                    arquivoIndice.Write('(');
                    arquivoIndice.Write(objetoValor.Documento);//id documento
                    arquivoIndice.Write(',');
                    arquivoIndice.Write(objetoValor.Posicao.Count); // frequencia no documento
                    foreach (var pos in objetoValor.Posicao) //Posições que apareceu
                    {
                        arquivoIndice.Write(',');
                        arquivoIndice.Write(pos);
                    }
                    arquivoIndice.Write(')');
                    arquivoIndice.Write('|');
                }
                arquivoIndice.WriteLine();
            }

            arquivoIndice.Close();
        }
    }
}
